package fun.sanguo.service.sys.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import fun.sanguo.caches.UserCache;
import fun.sanguo.config.DefaultConfig;
import fun.sanguo.mapper.sys.SysUserMapper;
import fun.sanguo.model.dto.DataInfo;
import fun.sanguo.model.dto.DataQuery;
import fun.sanguo.model.dto.PageInfo;
import fun.sanguo.model.dto.PageQuery;
import fun.sanguo.model.dto.sys.*;
import fun.sanguo.model.entity.sys.SysUserEntity;
import fun.sanguo.model.enums.DelFlagEnums;
import fun.sanguo.model.enums.ResEnums;
import fun.sanguo.model.enums.UserLoginEnums;
import fun.sanguo.model.enums.UserLogonEnums;
import fun.sanguo.service.sys.SysUserService;
import fun.sanguo.utils.EncryptUtils;
import fun.sanguo.utils.IdUtils;
import fun.sanguo.utils.RSAUtils;
import fun.sanguo.utils.exception.ArtificialException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

/**
 * 系统-用户信息 Service实现类
 *
 * @author ZYP
 * @date 2023-06-09
 */
@Service
public class SysUserServiceImpl implements SysUserService {

    @Resource
    private SysUserMapper sysUserMapper;

    @Resource
    private DefaultConfig defaultConfig;

    /**
     * 验证用户注册操作
     *
     * @param dataQuery
     * @return
     * @throws ArtificialException
     */
    @Override
    public DataInfo<SysUserLogonResult> logon(DataQuery<SysUserLogonParam> dataQuery) throws ArtificialException {
        // 验证结果
        SysUserLogonResult sysUserLogonResult = new SysUserLogonResult();
        // 注册参数
        String username, mobile, smsCaptcha;
        try {
            // 接收注册参数
            SysUserLogonParam sysUserLogonParam = new ObjectMapper().convertValue(dataQuery.getParam(), SysUserLogonParam.class);
            username = sysUserLogonParam.getUsername().trim();
            mobile = sysUserLogonParam.getMobile().trim();
            smsCaptcha = sysUserLogonParam.getSmsCaptcha().trim();
        } catch (Exception e) {
            throw new ArtificialException(ResEnums.ERR_PARAM.getCode(), ResEnums.ERR_PARAM.getMsg(), e);
        }
        // 获取内存中短信验证码
        String smsCaptchaInMemory = UserCache.getSmsCaptcha(mobile);
        // 判断短信验证码是否过期、是否正确
        if (StringUtils.isEmpty(smsCaptchaInMemory)) {
            sysUserLogonResult.setStatus(UserLogonEnums.SMS_CAPTCHA_EXPIRED);
        } else if (StringUtils.isEmpty(smsCaptcha) || !smsCaptchaInMemory.equals(smsCaptcha)) {
            sysUserLogonResult.setStatus(UserLogonEnums.SMS_CAPTCHA_INCORRECT);
        } else {
            // 根据注册账号查询用户信息
            List<SysUserEntity> userListByUsername = sysUserMapper.getByUsername(username);
            // 根据手机号码查询用户信息
            List<SysUserEntity> userListByMobile = sysUserMapper.getByMobile(mobile);
            // 登陆账号已存在
            if (userListByUsername != null && userListByUsername.size() > 0) {
                sysUserLogonResult.setStatus(UserLogonEnums.USER_REPEAT);
            } else if (userListByMobile != null && userListByMobile.size() > 0) {
                sysUserLogonResult.setStatus(UserLogonEnums.USER_MOBILE_REPEAT);
            } else {
                // 创建账号
                SysUserEntity sysUserEntity = new SysUserEntity();
                sysUserEntity.setId(String.valueOf(new IdUtils().nextId()));
                sysUserEntity.setUsercode(sysUserMapper.generateUsercode());
                sysUserEntity.setUsername(username);
                // TODO 暂时使用MD5
                try {
                    sysUserEntity.setPassword(EncryptUtils.toMD5(defaultConfig.getUser_password()));
                } catch (Exception e) {
                    throw new ArtificialException(ResEnums.EXCEPTION.getCode(), ResEnums.EXCEPTION.getMsg(), e);
                }
                sysUserEntity.setNickname("");
                sysUserEntity.setGender("");
                sysUserEntity.setAvatar("");
                sysUserEntity.setMobile(mobile);
                sysUserEntity.setWeixin("");
                // 判断结果
                if (sysUserMapper.insert(sysUserEntity) == 1) {
                    // 登陆成功
                    StpUtil.login(sysUserEntity.getId());
                    // 设置返回结果
                    sysUserLogonResult.setUserId(sysUserEntity.getId());
                    sysUserLogonResult.setToken(StpUtil.getTokenInfo());
                    sysUserLogonResult.setUserInfo(sysUserEntity);
                    sysUserLogonResult.setDefaultPassword(defaultConfig.getUser_password());
                    sysUserLogonResult.setStatus(UserLogonEnums.SUCCESS);
                }
            }
        }
        // 返回结果
        return new DataInfo<>(sysUserLogonResult);
    }

    /**
     * 验证用户登陆操作
     *
     * @param dataQuery
     * @return
     * @throws ArtificialException
     */
    @Override
    public DataInfo<SysUserLoginResult> login(DataQuery<SysUserLoginParam> dataQuery) throws ArtificialException {
        // 验证结果
        SysUserLoginResult sysUserLoginResult = new SysUserLoginResult();
        // 登陆参数
        String username, password, loginSeq, captcha;
        try {
            // 接收登陆参数
            SysUserLoginParam sysUserLoginParam = new ObjectMapper().convertValue(dataQuery.getParam(), SysUserLoginParam.class);
            username = sysUserLoginParam.getUsername().trim();
            password = EncryptUtils.fromRsaBase64ByPrivate(sysUserLoginParam.getPassword(), RSAUtils.getPrivateKey());
            loginSeq = sysUserLoginParam.getLoginSeq();
            captcha = sysUserLoginParam.getCaptcha().trim();
        } catch (Exception e) {
            throw new ArtificialException(ResEnums.ERR_PARAM.getCode(), ResEnums.ERR_PARAM.getMsg(), e);
        }
        // 验证登陆序列号
        if (StringUtils.isEmpty(loginSeq)) {
            throw new ArtificialException(ResEnums.ERR_PARAM.getCode(), ResEnums.ERR_PARAM.getMsg(), null);
        }
        // 获取内存中验证码
        String captchaInMemory = UserCache.getCaptcha(loginSeq);
        // 判断图形验证码是否过期、是否正确
        if (StringUtils.isEmpty(captchaInMemory)) {
            sysUserLoginResult.setStatus(UserLoginEnums.CAPTCHA_EXPIRED);
        } else if (StringUtils.isEmpty(captcha) || !captchaInMemory.equals(captcha)) {
            sysUserLoginResult.setStatus(UserLoginEnums.CAPTCHA_INCORRECT);
        } else {
            // 根据登陆账号查询用户信息（状态正常的应该只有一个，所以在遍历时遇到正常的便结束）
            List<SysUserEntity> sysUserEntityList = sysUserMapper.getByUsername(username);
            // 登陆账号不存在
            if (sysUserEntityList == null || sysUserEntityList.size() == 0) {
                sysUserLoginResult.setStatus(UserLoginEnums.USER_NOTFOUND);
            } else {
                SysUserEntity loginUser = null;
                // 遍历查找状态正常的用户
                for (SysUserEntity sysUserEntity : sysUserEntityList) {
                    if (DelFlagEnums.NORMAL.getCode().equals(sysUserEntity.getDelFlag())) {
                        loginUser = sysUserEntity;
                    }
                }
                // 是否找到状态正常的用户
                if (loginUser != null) {
                    // TODO 暂时使用MD5
                    try {
                        password = EncryptUtils.toMD5(password);
                    } catch (Exception e) {
                        throw new ArtificialException(ResEnums.EXCEPTION.getCode(), ResEnums.EXCEPTION.getMsg(), e);
                    }
                    // 判断是否与数据库中密码相同
                    if (password.equals(loginUser.getPassword())) {
                        // 是否仍然是初始密码
                        if (defaultConfig.getUser_password().equals(password)) {
                            sysUserLoginResult.setStatus(UserLoginEnums.PASSWORD_DEFAULTED);
                        } else {
                            // 登陆成功
                            StpUtil.login(loginUser.getId());
                            // 设置返回结果
                            sysUserLoginResult.setUserId(loginUser.getId());
                            sysUserLoginResult.setToken(StpUtil.getTokenInfo());
                            sysUserLoginResult.setUserInfo(loginUser);
                            sysUserLoginResult.setStatus(UserLoginEnums.SUCCESS);
                        }
                    } else {
                        sysUserLoginResult.setStatus(UserLoginEnums.PASSWORD_INCORRECT);
                    }
                } else {
                    sysUserLoginResult.setStatus(UserLoginEnums.USER_DELETED);
                }
            }
        }
        // 返回结果
        return new DataInfo<>(sysUserLoginResult);
    }

    /**
     * 获取当前登陆用户信息
     *
     * @return
     * @throws ArtificialException
     */
    @Override
    public DataInfo<SysUserEntity> getCurrentUser() throws ArtificialException {
        // 当前是否已登陆
        if (StpUtil.isLogin()) {
            // 获取当前登陆用户ID
            String userId = StpUtil.getLoginId().toString();
            // 查询用户信息
            SysUserEntity sysUserEntity = sysUserMapper.getById(userId);
            // 判断用户是否存在、状态是否正常
            if (sysUserEntity != null) {
                return new DataInfo<>(sysUserEntity);
            } else if (!DelFlagEnums.NORMAL.getCode().equals(sysUserEntity.getDelFlag())) {
                throw new ArtificialException(UserLoginEnums.USER_DELETED.getCode(), UserLoginEnums.USER_DELETED.getMsg(), null);
            } else {
                throw new ArtificialException(UserLoginEnums.USER_NOTFOUND.getCode(), UserLoginEnums.USER_NOTFOUND.getMsg(), null);
            }
        } else {
            throw new ArtificialException(ResEnums.ERR_USER_NOTLOGIN.getCode(), ResEnums.ERR_USER_NOTLOGIN.getMsg(), null);
        }
    }

    /**
     * 获取当前登陆用户ID
     *
     * @return
     * @throws ArtificialException
     */
    @Override
    public String getCurrentUserId() throws ArtificialException {
        // 当前是否已登陆
        if (StpUtil.isLogin()) {
            return StpUtil.getLoginId().toString();
        } else {
            throw new ArtificialException(ResEnums.ERR_USER_NOTLOGIN.getCode(), ResEnums.ERR_USER_NOTLOGIN.getMsg(), null);
        }
    }

    /**
     * 获取当前登陆用户ID或默认空
     *
     * @return
     */
    @Override
    public String getCurrentUserIdOrEmpty() {
        // 当前是否已登陆
        if (StpUtil.isLogin()) {
            return StpUtil.getLoginId().toString();
        } else {
            return "";
        }
    }

    /**
     * 查询页面table列表
     *
     * @param pageQuery
     * @return
     * @throws ArtificialException
     */
    @Override
    public PageInfo<SysUserEntity> getPage(PageQuery<SysUserParam> pageQuery) throws ArtificialException {
        // 查询参数
        SysUserEntity sysUserEntity = new SysUserEntity();
        // 转换查询参数
        try {
            // 接收参数
            SysUserParam sysUserParam = new ObjectMapper().convertValue(pageQuery.getParam(), SysUserParam.class);
            // 赋值到实体类
            BeanUtils.copyProperties(sysUserParam, sysUserEntity);
        } catch (Exception e) {
            throw new ArtificialException(ResEnums.ERR_PARAM.getCode(), ResEnums.ERR_PARAM.getMsg(), e);
        }
        // 查询数据并封装返回
        try {
            // 查询总量
            int total = sysUserMapper.getTotal(sysUserEntity);
            // 查询列表（分页）
            List<SysUserEntity> sysUserEntityList = sysUserMapper.getList(sysUserEntity, pageQuery);
            // 封装并返回页面信息
            return new PageInfo<>(sysUserEntityList, total, pageQuery);
        } catch (Exception e) {
            throw new ArtificialException(ResEnums.ERR_MYSQL.getCode(), ResEnums.ERR_MYSQL.getMsg(), e);
        }
    }
}
